package com.happy3w.cmds.maven.mermaid;

import com.happy3w.cmds.component.output.TextOutput;
import com.happy3w.cmds.maven.GraphOption;
import com.happy3w.cmds.maven.model.JavaModule;
import com.happy3w.cmds.maven.model.JavaModuleDictionary;
import lombok.RequiredArgsConstructor;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@RequiredArgsConstructor
public class MermaidDrawer {
    private final JavaModuleDictionary dictionary;
    private final GraphOption option;
    public void draw(TextOutput output) {
        output.outputLine("graph TD");
        DeclareOutput declareOutput = new DeclareOutput();
        dictionary.getParentModules().stream()
                .flatMap(JavaModule::streamAllSubModules)
                .forEach(module -> {
                    if (module.getPackaging().equals("pom")) {
                        if (!option.isShowGroup()) {
                            return;
                        }
                        output.outputLine("subgraph " + module.takeKey());
                        module.streamSubModules()
                                .forEach(subModule -> {
                                    declareOutput.output(subModule, output);
                                });
                        output.outputLine("end");
                    } else {
                        declareOutput.output(module, output);
                    }
                });

        dictionary.streamAllModules()
                .forEach(module -> {
                    module.getDependencies().stream()
                            .map(d -> dictionary.getModuleMap().get(d))
                            .filter(Objects::nonNull)
                            .forEach(d -> {
                                output.outputLine(module.getCode() + " --> " + d.getCode());
                            });
                });
    }

    private class DeclareOutput {
        private Set<JavaModule> declared = new HashSet<>();

        public void output(JavaModule subModule, TextOutput output) {
            if (declared.contains(subModule)) {
                return;
            }
            declared.add(subModule);
            String display = option.isShowGroup() ? subModule.takeKey() : subModule.getArtifactId();
            output.outputLine(subModule.getCode() + "(" + display + ")");
        }
    }
}
